<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta http-equiv="X-UA-Compatible" content="IE=EDGE" />

<meta name="viewport" content="width=device-width, initial-scale=1" />

<meta name="author" content="Nickalus Redell" />

<meta name="date" content="2020-04-19" />

<title>Forecast Combination</title>



<style type="text/css">code{white-space: pre;}</style>
<style type="text/css" data-origin="pandoc">
code.sourceCode > span { display: inline-block; line-height: 1.25; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
  { counter-reset: source-line 0; }
pre.numberSource code > span
  { position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
  { content: counter(source-line);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; display: inline-block;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
    color: #aaaaaa;
  }
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
div.sourceCode
  {   }
@media screen {
code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */

</style>
<script>
// apply pandoc div.sourceCode style to pre.sourceCode instead
(function() {
  var sheets = document.styleSheets;
  for (var i = 0; i < sheets.length; i++) {
    if (sheets[i].ownerNode.dataset["origin"] !== "pandoc") continue;
    try { var rules = sheets[i].cssRules; } catch (e) { continue; }
    for (var j = 0; j < rules.length; j++) {
      var rule = rules[j];
      // check if there is a div.sourceCode rule
      if (rule.type !== rule.STYLE_RULE || rule.selectorText !== "div.sourceCode") continue;
      var style = rule.style.cssText;
      // check if color or background-color is set
      if (rule.style.color === '' && rule.style.backgroundColor === '') continue;
      // replace div.sourceCode by a pre.sourceCode rule
      sheets[i].deleteRule(j);
      sheets[i].insertRule('pre.sourceCode{' + style + '}', j);
    }
  }
})();
</script>



<style type="text/css">body {
background-color: #fff;
margin: 1em auto;
max-width: 700px;
overflow: visible;
padding-left: 2em;
padding-right: 2em;
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.35;
}
#TOC {
clear: both;
margin: 0 0 10px 10px;
padding: 4px;
width: 400px;
border: 1px solid #CCCCCC;
border-radius: 5px;
background-color: #f6f6f6;
font-size: 13px;
line-height: 1.3;
}
#TOC .toctitle {
font-weight: bold;
font-size: 15px;
margin-left: 5px;
}
#TOC ul {
padding-left: 40px;
margin-left: -1.5em;
margin-top: 5px;
margin-bottom: 5px;
}
#TOC ul ul {
margin-left: -2em;
}
#TOC li {
line-height: 16px;
}
table {
margin: 1em auto;
border-width: 1px;
border-color: #DDDDDD;
border-style: outset;
border-collapse: collapse;
}
table th {
border-width: 2px;
padding: 5px;
border-style: inset;
}
table td {
border-width: 1px;
border-style: inset;
line-height: 18px;
padding: 5px 5px;
}
table, table th, table td {
border-left-style: none;
border-right-style: none;
}
table thead, table tr.even {
background-color: #f7f7f7;
}
p {
margin: 0.5em 0;
}
blockquote {
background-color: #f6f6f6;
padding: 0.25em 0.75em;
}
hr {
border-style: solid;
border: none;
border-top: 1px solid #777;
margin: 28px 0;
}
dl {
margin-left: 0;
}
dl dd {
margin-bottom: 13px;
margin-left: 13px;
}
dl dt {
font-weight: bold;
}
ul {
margin-top: 0;
}
ul li {
list-style: circle outside;
}
ul ul {
margin-bottom: 0;
}
pre, code {
background-color: #f7f7f7;
border-radius: 3px;
color: #333;
white-space: pre-wrap; 
}
pre {
border-radius: 3px;
margin: 5px 0px 10px 0px;
padding: 10px;
}
pre:not([class]) {
background-color: #f7f7f7;
}
code {
font-family: Consolas, Monaco, 'Courier New', monospace;
font-size: 85%;
}
p > code, li > code {
padding: 2px 0px;
}
div.figure {
text-align: center;
}
img {
background-color: #FFFFFF;
padding: 2px;
border: 1px solid #DDDDDD;
border-radius: 3px;
border: 1px solid #CCCCCC;
margin: 0 5px;
}
h1 {
margin-top: 0;
font-size: 35px;
line-height: 40px;
}
h2 {
border-bottom: 4px solid #f7f7f7;
padding-top: 10px;
padding-bottom: 2px;
font-size: 145%;
}
h3 {
border-bottom: 2px solid #f7f7f7;
padding-top: 10px;
font-size: 120%;
}
h4 {
border-bottom: 1px solid #f7f7f7;
margin-left: 8px;
font-size: 105%;
}
h5, h6 {
border-bottom: 1px solid #ccc;
font-size: 105%;
}
a {
color: #0033dd;
text-decoration: none;
}
a:hover {
color: #6666ff; }
a:visited {
color: #800080; }
a:visited:hover {
color: #BB00BB; }
a[href^="http:"] {
text-decoration: underline; }
a[href^="https:"] {
text-decoration: underline; }

code > span.kw { color: #555; font-weight: bold; } 
code > span.dt { color: #902000; } 
code > span.dv { color: #40a070; } 
code > span.bn { color: #d14; } 
code > span.fl { color: #d14; } 
code > span.ch { color: #d14; } 
code > span.st { color: #d14; } 
code > span.co { color: #888888; font-style: italic; } 
code > span.ot { color: #007020; } 
code > span.al { color: #ff0000; font-weight: bold; } 
code > span.fu { color: #900; font-weight: bold; } 
code > span.er { color: #a61717; background-color: #e3d2d2; } 
</style>




</head>

<body>




<h1 class="title toc-ignore"><strong>Forecast Combination</strong></h1>
<h4 class="author">Nickalus Redell</h4>
<h4 class="date">2020-04-19</h4>



<div id="purpose" class="section level1">
<h1><strong>Purpose</strong></h1>
<p>The purpose of this vignette is to illustrate the various approaches in <code>forecsatML</code> for producing final forecasts that are (a) a combination of short- and long-term forecasts as well as (b) a combination of many ML models at select forecast horizons.</p>
<p>The goal of <code>forecastML::combine_forecasts()</code> is to provide maximum flexibility when producing a single forecast that is expected to perform as well in the near-term as it is in the long-term.</p>
</div>
<div id="forecast-combination-by-horizon" class="section level1">
<h1><strong>Forecast Combination by Horizon</strong></h1>
<ul>
<li><p>Forecast combinations with <code>forecastML::combine_forecasts(..., type = &quot;horizon&quot;)</code> are a simple and effective method for producing final forecasts that consist of (a) an ensemble of short- and long-term forecasts and (b) an ensemble of separately trained ML models at any forecast horizon.</p></li>
<li><p>Below are 3 examples:</p>
<ul>
<li>1: An ensemble of short- and long-term forecasts</li>
<li>2: An ensemble of short- and long-term forecasts with separately trained ML models</li>
<li>3: An ensemble of short- and long-term forecasts with a cross-sectional ensemble of models at select horizons</li>
</ul></li>
</ul>
<div id="load-packages-data" class="section level2">
<h2><strong>Load Packages &amp; Data</strong></h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw">library</span>(forecastML)</span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw">library</span>(dplyr)</span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="kw">library</span>(ggplot2)</span>
<span id="cb1-4"><a href="#cb1-4"></a><span class="kw">library</span>(glmnet)</span>
<span id="cb1-5"><a href="#cb1-5"></a></span>
<span id="cb1-6"><a href="#cb1-6"></a><span class="kw">data</span>(<span class="st">&quot;data_seatbelts&quot;</span>, <span class="dt">package =</span> <span class="st">&quot;forecastML&quot;</span>)</span>
<span id="cb1-7"><a href="#cb1-7"></a>data &lt;-<span class="st"> </span>data_seatbelts</span></code></pre></div>
</div>
<div id="one-model-training-function" class="section level2">
<h2><strong>1: One Model Training Function</strong></h2>
<ul>
<li><strong>Setup:</strong>
<ul>
<li>1 model training function (could consist of an ensemble of models).</li>
<li>Multiple direct forecast horizons.
<p></li>
</ul></li>
<li><strong>Combination:</strong>
<ul>
<li>Greedy: Models with shorter direct forecast horizons produce near-term forecasts, and models with longer direct forecast horizons only produce forecasts at horizons above and beyond those from the short-term models.
<p></li>
</ul></li>
<li><strong>Pros:</strong>
<ul>
<li>Easy to implement.
<p></li>
</ul></li>
<li><strong>Cons:</strong>
<ul>
<li>If the model training function uses 1 ML algorithm–e.g., a neural network–to build both short- and long-term direct forecast models–which will have different parameters/hyperparameters–, it could be the case that entirely different model classes–e.g., support vector machines–may produce better short- or long-term final forecasts if included in the forecast combination.
<p></li>
</ul></li>
</ul>
<p><img src="" height="400" /></p>
<p><br></p>
<ul>
<li><strong>Example:</strong></li>
</ul>
<div class="sourceCode" id="cb2"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb2-1"><a href="#cb2-1"></a>horizons &lt;-<span class="st"> </span><span class="kw">c</span>(<span class="dv">1</span>, <span class="dv">3</span>, <span class="dv">6</span>, <span class="dv">9</span>, <span class="dv">12</span>)</span>
<span id="cb2-2"><a href="#cb2-2"></a>data_train &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_lagged_df</span>(data_seatbelts, <span class="dt">type =</span> <span class="st">&quot;train&quot;</span>, <span class="dt">method =</span> <span class="st">&quot;direct&quot;</span>,</span>
<span id="cb2-3"><a href="#cb2-3"></a>                                           <span class="dt">outcome_col =</span> <span class="dv">1</span>, <span class="dt">lookback =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">15</span>, <span class="dt">horizon =</span> horizons)</span>
<span id="cb2-4"><a href="#cb2-4"></a></span>
<span id="cb2-5"><a href="#cb2-5"></a>windows &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_windows</span>(data_train, <span class="dt">window_length =</span> <span class="dv">0</span>)</span>
<span id="cb2-6"><a href="#cb2-6"></a></span>
<span id="cb2-7"><a href="#cb2-7"></a>model_fun &lt;-<span class="st"> </span><span class="cf">function</span>(data) {</span>
<span id="cb2-8"><a href="#cb2-8"></a>  x &lt;-<span class="st"> </span><span class="kw">as.matrix</span>(data[, <span class="dv">-1</span>, <span class="dt">drop =</span> <span class="ot">FALSE</span>])</span>
<span id="cb2-9"><a href="#cb2-9"></a>  y &lt;-<span class="st"> </span><span class="kw">as.matrix</span>(data[, <span class="dv">1</span>, <span class="dt">drop =</span> <span class="ot">FALSE</span>])</span>
<span id="cb2-10"><a href="#cb2-10"></a>  <span class="kw">set.seed</span>(<span class="dv">1</span>)</span>
<span id="cb2-11"><a href="#cb2-11"></a>  model &lt;-<span class="st"> </span>glmnet<span class="op">::</span><span class="kw">cv.glmnet</span>(x, y)</span>
<span id="cb2-12"><a href="#cb2-12"></a>}</span>
<span id="cb2-13"><a href="#cb2-13"></a></span>
<span id="cb2-14"><a href="#cb2-14"></a>model_results &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">train_model</span>(data_train, windows, <span class="dt">model_name =</span> <span class="st">&quot;LASSO&quot;</span>, <span class="dt">model_function =</span> model_fun)</span>
<span id="cb2-15"><a href="#cb2-15"></a></span>
<span id="cb2-16"><a href="#cb2-16"></a>prediction_fun &lt;-<span class="st"> </span><span class="cf">function</span>(model, data_features) {</span>
<span id="cb2-17"><a href="#cb2-17"></a>  data_pred &lt;-<span class="st"> </span><span class="kw">data.frame</span>(<span class="st">&quot;y_pred&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)),</span>
<span id="cb2-18"><a href="#cb2-18"></a>                          <span class="st">&quot;y_pred_lower&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)) <span class="op">-</span><span class="st"> </span><span class="dv">30</span>,</span>
<span id="cb2-19"><a href="#cb2-19"></a>                          <span class="st">&quot;y_pred_upper&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)) <span class="op">+</span><span class="st"> </span><span class="dv">30</span>)</span>
<span id="cb2-20"><a href="#cb2-20"></a>}</span>
<span id="cb2-21"><a href="#cb2-21"></a></span>
<span id="cb2-22"><a href="#cb2-22"></a>data_forecast &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_lagged_df</span>(data_seatbelts, <span class="dt">type =</span> <span class="st">&quot;forecast&quot;</span>, <span class="dt">method =</span> <span class="st">&quot;direct&quot;</span>,</span>
<span id="cb2-23"><a href="#cb2-23"></a>                                              <span class="dt">outcome_col =</span> <span class="dv">1</span>, <span class="dt">lookback =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">15</span>, <span class="dt">horizon =</span> horizons)</span>
<span id="cb2-24"><a href="#cb2-24"></a></span>
<span id="cb2-25"><a href="#cb2-25"></a>data_forecasts &lt;-<span class="st"> </span><span class="kw">predict</span>(model_results, <span class="dt">prediction_function =</span> <span class="kw">list</span>(prediction_fun), <span class="dt">data =</span> data_forecast)</span>
<span id="cb2-26"><a href="#cb2-26"></a></span>
<span id="cb2-27"><a href="#cb2-27"></a>data_forecasts &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">combine_forecasts</span>(data_forecasts, <span class="dt">type =</span> <span class="st">&quot;horizon&quot;</span>)</span>
<span id="cb2-28"><a href="#cb2-28"></a></span>
<span id="cb2-29"><a href="#cb2-29"></a><span class="kw">plot</span>(data_forecasts, <span class="dt">data_actual =</span> data_seatbelts[<span class="op">-</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">170</span>), ], <span class="dt">actual_indices =</span> (<span class="dv">1</span><span class="op">:</span><span class="kw">nrow</span>(data_seatbelts))[<span class="op">-</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">170</span>)])</span></code></pre></div>
<p><img src="" /><!-- --></p>
<hr />
</div>
<div id="multiple-model-training-functions" class="section level2">
<h2><strong>2: Multiple Model Training Functions</strong></h2>
<ul>
<li><strong>Setup:</strong>
<ul>
<li>2 or more model training functions.</li>
<li>Multiple direct forecast horizons.
<p></li>
</ul></li>
<li><strong>Combination:</strong>
<ul>
<li>Greedy: Models with shorter direct forecast horizons produce near-term forecasts, and models with longer direct forecast horizons only produce forecasts at horizons above and beyond those from the short-term models.</li>
<li>If multiple model training functions produce models with the same direct forecast horizon, forecasts for the shared horizon(s) are combined with the function passed in <code>combine_forecasts(..., agregate = function)</code> (see example 3 below).
<p></li>
</ul></li>
<li><strong>Pros:</strong>
<ul>
<li>Gives precise control over the algorithms used to produce short- and long-term forecasts. For example, a large neural network may produce the best short-term forecasts while a linear model may produce the best long-term forecasts.</li>
<li>Also useful with large data when training multiple direct forecast models with one call to <code>forecastML::train_model()</code> uses too much memory. Here, you would train one model at a time and combine them with <code>forecastML::combine_forecasts()</code>.
<p></li>
</ul></li>
<li><strong>Cons:</strong>
<ul>
<li>More code.
<p></li>
</ul></li>
</ul>
<p><img src="" height="400" /></p>
<p><br></p>
<ul>
<li><strong>Example:</strong></li>
</ul>
<div class="sourceCode" id="cb3"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb3-1"><a href="#cb3-1"></a><span class="co"># LASSO</span></span>
<span id="cb3-2"><a href="#cb3-2"></a></span>
<span id="cb3-3"><a href="#cb3-3"></a>horizons &lt;-<span class="st"> </span><span class="kw">c</span>(<span class="dv">1</span>, <span class="dv">3</span>, <span class="dv">6</span>)</span>
<span id="cb3-4"><a href="#cb3-4"></a>data_train &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_lagged_df</span>(data_seatbelts, <span class="dt">type =</span> <span class="st">&quot;train&quot;</span>, <span class="dt">method =</span> <span class="st">&quot;direct&quot;</span>,</span>
<span id="cb3-5"><a href="#cb3-5"></a>                                           <span class="dt">outcome_col =</span> <span class="dv">1</span>, <span class="dt">lookback =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">15</span>, <span class="dt">horizon =</span> horizons)</span>
<span id="cb3-6"><a href="#cb3-6"></a></span>
<span id="cb3-7"><a href="#cb3-7"></a>windows &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_windows</span>(data_train, <span class="dt">window_length =</span> <span class="dv">0</span>)</span>
<span id="cb3-8"><a href="#cb3-8"></a></span>
<span id="cb3-9"><a href="#cb3-9"></a>model_fun_lasso &lt;-<span class="st"> </span><span class="cf">function</span>(data) {</span>
<span id="cb3-10"><a href="#cb3-10"></a>  x &lt;-<span class="st"> </span><span class="kw">as.matrix</span>(data[, <span class="dv">-1</span>, <span class="dt">drop =</span> <span class="ot">FALSE</span>])</span>
<span id="cb3-11"><a href="#cb3-11"></a>  y &lt;-<span class="st"> </span><span class="kw">as.matrix</span>(data[, <span class="dv">1</span>, <span class="dt">drop =</span> <span class="ot">FALSE</span>])</span>
<span id="cb3-12"><a href="#cb3-12"></a>  <span class="kw">set.seed</span>(<span class="dv">1</span>)</span>
<span id="cb3-13"><a href="#cb3-13"></a>  model &lt;-<span class="st"> </span>glmnet<span class="op">::</span><span class="kw">cv.glmnet</span>(x, y, <span class="dt">alpha =</span> <span class="dv">1</span>)</span>
<span id="cb3-14"><a href="#cb3-14"></a>}</span>
<span id="cb3-15"><a href="#cb3-15"></a></span>
<span id="cb3-16"><a href="#cb3-16"></a>model_results &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">train_model</span>(data_train, windows, <span class="dt">model_name =</span> <span class="st">&quot;LASSO&quot;</span>, <span class="dt">model_function =</span> model_fun_lasso)</span>
<span id="cb3-17"><a href="#cb3-17"></a></span>
<span id="cb3-18"><a href="#cb3-18"></a>prediction_fun &lt;-<span class="st"> </span><span class="cf">function</span>(model, data_features) {</span>
<span id="cb3-19"><a href="#cb3-19"></a>  data_pred &lt;-<span class="st"> </span><span class="kw">data.frame</span>(<span class="st">&quot;y_pred&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)),</span>
<span id="cb3-20"><a href="#cb3-20"></a>                          <span class="st">&quot;y_pred_lower&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)) <span class="op">-</span><span class="st"> </span><span class="dv">30</span>,</span>
<span id="cb3-21"><a href="#cb3-21"></a>                          <span class="st">&quot;y_pred_upper&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)) <span class="op">+</span><span class="st"> </span><span class="dv">30</span>)</span>
<span id="cb3-22"><a href="#cb3-22"></a>}</span>
<span id="cb3-23"><a href="#cb3-23"></a></span>
<span id="cb3-24"><a href="#cb3-24"></a>data_forecast &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_lagged_df</span>(data_seatbelts, <span class="dt">type =</span> <span class="st">&quot;forecast&quot;</span>, <span class="dt">method =</span> <span class="st">&quot;direct&quot;</span>,</span>
<span id="cb3-25"><a href="#cb3-25"></a>                                              <span class="dt">outcome_col =</span> <span class="dv">1</span>, <span class="dt">lookback =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">15</span>, <span class="dt">horizon =</span> horizons)</span>
<span id="cb3-26"><a href="#cb3-26"></a></span>
<span id="cb3-27"><a href="#cb3-27"></a>data_forecasts_lasso &lt;-<span class="st"> </span><span class="kw">predict</span>(model_results, <span class="dt">prediction_function =</span> <span class="kw">list</span>(prediction_fun), <span class="dt">data =</span> data_forecast)</span>
<span id="cb3-28"><a href="#cb3-28"></a><span class="co">#------------------------------------------------------------------------------</span></span>
<span id="cb3-29"><a href="#cb3-29"></a><span class="co"># Ridge</span></span>
<span id="cb3-30"><a href="#cb3-30"></a></span>
<span id="cb3-31"><a href="#cb3-31"></a>horizons &lt;-<span class="st"> </span><span class="kw">c</span>(<span class="dv">9</span>, <span class="dv">12</span>)</span>
<span id="cb3-32"><a href="#cb3-32"></a>data_train &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_lagged_df</span>(data_seatbelts, <span class="dt">type =</span> <span class="st">&quot;train&quot;</span>, <span class="dt">method =</span> <span class="st">&quot;direct&quot;</span>,</span>
<span id="cb3-33"><a href="#cb3-33"></a>                                           <span class="dt">outcome_col =</span> <span class="dv">1</span>, <span class="dt">lookback =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">15</span>, <span class="dt">horizon =</span> horizons)</span>
<span id="cb3-34"><a href="#cb3-34"></a></span>
<span id="cb3-35"><a href="#cb3-35"></a>windows &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_windows</span>(data_train, <span class="dt">window_length =</span> <span class="dv">0</span>)</span>
<span id="cb3-36"><a href="#cb3-36"></a></span>
<span id="cb3-37"><a href="#cb3-37"></a>model_fun_ridge &lt;-<span class="st"> </span><span class="cf">function</span>(data) {</span>
<span id="cb3-38"><a href="#cb3-38"></a>  x &lt;-<span class="st"> </span><span class="kw">as.matrix</span>(data[, <span class="dv">-1</span>, <span class="dt">drop =</span> <span class="ot">FALSE</span>])</span>
<span id="cb3-39"><a href="#cb3-39"></a>  y &lt;-<span class="st"> </span><span class="kw">as.matrix</span>(data[, <span class="dv">1</span>, <span class="dt">drop =</span> <span class="ot">FALSE</span>])</span>
<span id="cb3-40"><a href="#cb3-40"></a>  <span class="kw">set.seed</span>(<span class="dv">1</span>)</span>
<span id="cb3-41"><a href="#cb3-41"></a>  model &lt;-<span class="st"> </span>glmnet<span class="op">::</span><span class="kw">cv.glmnet</span>(x, y, <span class="dt">alpha =</span> <span class="dv">0</span>)</span>
<span id="cb3-42"><a href="#cb3-42"></a>}</span>
<span id="cb3-43"><a href="#cb3-43"></a></span>
<span id="cb3-44"><a href="#cb3-44"></a>model_results &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">train_model</span>(data_train, windows, <span class="dt">model_name =</span> <span class="st">&quot;Ridge&quot;</span>, <span class="dt">model_function =</span> model_fun_ridge)</span>
<span id="cb3-45"><a href="#cb3-45"></a></span>
<span id="cb3-46"><a href="#cb3-46"></a>prediction_fun &lt;-<span class="st"> </span><span class="cf">function</span>(model, data_features) {</span>
<span id="cb3-47"><a href="#cb3-47"></a>  data_pred &lt;-<span class="st"> </span><span class="kw">data.frame</span>(<span class="st">&quot;y_pred&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)),</span>
<span id="cb3-48"><a href="#cb3-48"></a>                          <span class="st">&quot;y_pred_lower&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)) <span class="op">-</span><span class="st"> </span><span class="dv">30</span>,</span>
<span id="cb3-49"><a href="#cb3-49"></a>                          <span class="st">&quot;y_pred_upper&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)) <span class="op">+</span><span class="st"> </span><span class="dv">30</span>)</span>
<span id="cb3-50"><a href="#cb3-50"></a>}</span>
<span id="cb3-51"><a href="#cb3-51"></a></span>
<span id="cb3-52"><a href="#cb3-52"></a>data_forecast &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_lagged_df</span>(data_seatbelts, <span class="dt">type =</span> <span class="st">&quot;forecast&quot;</span>, <span class="dt">method =</span> <span class="st">&quot;direct&quot;</span>,</span>
<span id="cb3-53"><a href="#cb3-53"></a>                                              <span class="dt">outcome_col =</span> <span class="dv">1</span>, <span class="dt">lookback =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">15</span>, <span class="dt">horizon =</span> horizons)</span>
<span id="cb3-54"><a href="#cb3-54"></a></span>
<span id="cb3-55"><a href="#cb3-55"></a>data_forecasts_ridge &lt;-<span class="st"> </span><span class="kw">predict</span>(model_results, <span class="dt">prediction_function =</span> <span class="kw">list</span>(prediction_fun), <span class="dt">data =</span> data_forecast)</span>
<span id="cb3-56"><a href="#cb3-56"></a><span class="co">#------------------------------------------------------------------------------</span></span>
<span id="cb3-57"><a href="#cb3-57"></a><span class="co"># Forecast combination.</span></span>
<span id="cb3-58"><a href="#cb3-58"></a></span>
<span id="cb3-59"><a href="#cb3-59"></a>data_forecasts &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">combine_forecasts</span>(data_forecasts_lasso, data_forecasts_ridge, <span class="dt">type =</span> <span class="st">&quot;horizon&quot;</span>)</span>
<span id="cb3-60"><a href="#cb3-60"></a></span>
<span id="cb3-61"><a href="#cb3-61"></a><span class="kw">plot</span>(data_forecasts, <span class="dt">data_actual =</span> data_seatbelts[<span class="op">-</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">170</span>), ], <span class="dt">actual_indices =</span> (<span class="dv">1</span><span class="op">:</span><span class="kw">nrow</span>(data_seatbelts))[<span class="op">-</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">170</span>)])</span></code></pre></div>
<p><img src="" /><!-- --></p>
<hr />
</div>
<div id="multiple-model-training-functions---aggregation" class="section level2">
<h2><strong>3: Multiple Model Training Functions - Aggregation</strong></h2>
<ul>
<li><strong>Setup:</strong>
<ul>
<li>2 or more model training functions.</li>
<li>The model training functions share the same direct forecast horizons (complete overlap is not necessary).</li>
<li>Multiple direct forecast horizons.
<p></li>
</ul></li>
<li><strong>Combination:</strong>
<ul>
<li>If multiple model training functions produce models with the same direct forecast horizon, forecasts for the shared horizon(s) are combined with the function passed in <code>combine_forecasts(..., agregate = function)</code>.</li>
<li>The default combination for shared horizons is <code>median()</code>.</li>
<li>Greedy: Models with shorter direct forecast horizons produce near-term forecasts, and models with longer direct forecast horizons only produce forecasts at horizons above and beyond those from the short-term models.
<p></li>
</ul></li>
<li><strong>Pros:</strong>
<ul>
<li>A simple way to produce ensemble forecasts at a given forecast horizon.
<p></li>
</ul></li>
<li><strong>Cons:</strong>
<ul>
<li>More code.
<p></li>
</ul></li>
</ul>
<p><img src="" height="400" /></p>
<p><br></p>
<ul>
<li><strong>Example:</strong></li>
</ul>
<div class="sourceCode" id="cb4"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb4-1"><a href="#cb4-1"></a><span class="co"># LASSO</span></span>
<span id="cb4-2"><a href="#cb4-2"></a></span>
<span id="cb4-3"><a href="#cb4-3"></a>horizons &lt;-<span class="st"> </span><span class="kw">c</span>(<span class="dv">1</span>, <span class="dv">3</span>, <span class="dv">6</span>, <span class="dv">9</span>, <span class="dv">12</span>)</span>
<span id="cb4-4"><a href="#cb4-4"></a>data_train &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_lagged_df</span>(data_seatbelts, <span class="dt">type =</span> <span class="st">&quot;train&quot;</span>, <span class="dt">method =</span> <span class="st">&quot;direct&quot;</span>,</span>
<span id="cb4-5"><a href="#cb4-5"></a>                                           <span class="dt">outcome_col =</span> <span class="dv">1</span>, <span class="dt">lookback =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">15</span>, <span class="dt">horizon =</span> horizons)</span>
<span id="cb4-6"><a href="#cb4-6"></a></span>
<span id="cb4-7"><a href="#cb4-7"></a>windows &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_windows</span>(data_train, <span class="dt">window_length =</span> <span class="dv">0</span>)</span>
<span id="cb4-8"><a href="#cb4-8"></a></span>
<span id="cb4-9"><a href="#cb4-9"></a>model_fun_lasso &lt;-<span class="st"> </span><span class="cf">function</span>(data) {</span>
<span id="cb4-10"><a href="#cb4-10"></a>  x &lt;-<span class="st"> </span><span class="kw">as.matrix</span>(data[, <span class="dv">-1</span>, <span class="dt">drop =</span> <span class="ot">FALSE</span>])</span>
<span id="cb4-11"><a href="#cb4-11"></a>  y &lt;-<span class="st"> </span><span class="kw">as.matrix</span>(data[, <span class="dv">1</span>, <span class="dt">drop =</span> <span class="ot">FALSE</span>])</span>
<span id="cb4-12"><a href="#cb4-12"></a>  <span class="kw">set.seed</span>(<span class="dv">1</span>)</span>
<span id="cb4-13"><a href="#cb4-13"></a>  model &lt;-<span class="st"> </span>glmnet<span class="op">::</span><span class="kw">cv.glmnet</span>(x, y, <span class="dt">alpha =</span> <span class="dv">1</span>)</span>
<span id="cb4-14"><a href="#cb4-14"></a>}</span>
<span id="cb4-15"><a href="#cb4-15"></a></span>
<span id="cb4-16"><a href="#cb4-16"></a>model_results &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">train_model</span>(data_train, windows, <span class="dt">model_name =</span> <span class="st">&quot;LASSO&quot;</span>, <span class="dt">model_function =</span> model_fun_lasso)</span>
<span id="cb4-17"><a href="#cb4-17"></a></span>
<span id="cb4-18"><a href="#cb4-18"></a>prediction_fun &lt;-<span class="st"> </span><span class="cf">function</span>(model, data_features) {</span>
<span id="cb4-19"><a href="#cb4-19"></a>  data_pred &lt;-<span class="st"> </span><span class="kw">data.frame</span>(<span class="st">&quot;y_pred&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)),</span>
<span id="cb4-20"><a href="#cb4-20"></a>                          <span class="st">&quot;y_pred_lower&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)) <span class="op">-</span><span class="st"> </span><span class="dv">30</span>,</span>
<span id="cb4-21"><a href="#cb4-21"></a>                          <span class="st">&quot;y_pred_upper&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)) <span class="op">+</span><span class="st"> </span><span class="dv">30</span>)</span>
<span id="cb4-22"><a href="#cb4-22"></a>}</span>
<span id="cb4-23"><a href="#cb4-23"></a></span>
<span id="cb4-24"><a href="#cb4-24"></a>data_forecast &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_lagged_df</span>(data_seatbelts, <span class="dt">type =</span> <span class="st">&quot;forecast&quot;</span>, <span class="dt">method =</span> <span class="st">&quot;direct&quot;</span>,</span>
<span id="cb4-25"><a href="#cb4-25"></a>                                              <span class="dt">outcome_col =</span> <span class="dv">1</span>, <span class="dt">lookback =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">15</span>, <span class="dt">horizon =</span> horizons)</span>
<span id="cb4-26"><a href="#cb4-26"></a></span>
<span id="cb4-27"><a href="#cb4-27"></a>data_forecasts_lasso &lt;-<span class="st"> </span><span class="kw">predict</span>(model_results, <span class="dt">prediction_function =</span> <span class="kw">list</span>(prediction_fun), <span class="dt">data =</span> data_forecast)</span>
<span id="cb4-28"><a href="#cb4-28"></a><span class="co">#------------------------------------------------------------------------------</span></span>
<span id="cb4-29"><a href="#cb4-29"></a><span class="co"># Ridge</span></span>
<span id="cb4-30"><a href="#cb4-30"></a></span>
<span id="cb4-31"><a href="#cb4-31"></a>horizons &lt;-<span class="st"> </span><span class="kw">c</span>(<span class="dv">1</span>, <span class="dv">3</span>, <span class="dv">6</span>, <span class="dv">9</span>, <span class="dv">12</span>)</span>
<span id="cb4-32"><a href="#cb4-32"></a>data_train &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_lagged_df</span>(data_seatbelts, <span class="dt">type =</span> <span class="st">&quot;train&quot;</span>, <span class="dt">method =</span> <span class="st">&quot;direct&quot;</span>,</span>
<span id="cb4-33"><a href="#cb4-33"></a>                                           <span class="dt">outcome_col =</span> <span class="dv">1</span>, <span class="dt">lookback =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">15</span>, <span class="dt">horizon =</span> horizons)</span>
<span id="cb4-34"><a href="#cb4-34"></a></span>
<span id="cb4-35"><a href="#cb4-35"></a>windows &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_windows</span>(data_train, <span class="dt">window_length =</span> <span class="dv">0</span>)</span>
<span id="cb4-36"><a href="#cb4-36"></a></span>
<span id="cb4-37"><a href="#cb4-37"></a>model_fun_ridge &lt;-<span class="st"> </span><span class="cf">function</span>(data) {</span>
<span id="cb4-38"><a href="#cb4-38"></a>  x &lt;-<span class="st"> </span><span class="kw">as.matrix</span>(data[, <span class="dv">-1</span>, <span class="dt">drop =</span> <span class="ot">FALSE</span>])</span>
<span id="cb4-39"><a href="#cb4-39"></a>  y &lt;-<span class="st"> </span><span class="kw">as.matrix</span>(data[, <span class="dv">1</span>, <span class="dt">drop =</span> <span class="ot">FALSE</span>])</span>
<span id="cb4-40"><a href="#cb4-40"></a>  <span class="kw">set.seed</span>(<span class="dv">1</span>)</span>
<span id="cb4-41"><a href="#cb4-41"></a>  model &lt;-<span class="st"> </span>glmnet<span class="op">::</span><span class="kw">cv.glmnet</span>(x, y, <span class="dt">alpha =</span> <span class="dv">0</span>)</span>
<span id="cb4-42"><a href="#cb4-42"></a>}</span>
<span id="cb4-43"><a href="#cb4-43"></a></span>
<span id="cb4-44"><a href="#cb4-44"></a>model_results &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">train_model</span>(data_train, windows, <span class="dt">model_name =</span> <span class="st">&quot;Ridge&quot;</span>, <span class="dt">model_function =</span> model_fun_ridge)</span>
<span id="cb4-45"><a href="#cb4-45"></a></span>
<span id="cb4-46"><a href="#cb4-46"></a>prediction_fun &lt;-<span class="st"> </span><span class="cf">function</span>(model, data_features) {</span>
<span id="cb4-47"><a href="#cb4-47"></a>  data_pred &lt;-<span class="st"> </span><span class="kw">data.frame</span>(<span class="st">&quot;y_pred&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)),</span>
<span id="cb4-48"><a href="#cb4-48"></a>                          <span class="st">&quot;y_pred_lower&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)) <span class="op">-</span><span class="st"> </span><span class="dv">30</span>,</span>
<span id="cb4-49"><a href="#cb4-49"></a>                          <span class="st">&quot;y_pred_upper&quot;</span> =<span class="st"> </span><span class="kw">predict</span>(model, <span class="kw">as.matrix</span>(data_features)) <span class="op">+</span><span class="st"> </span><span class="dv">30</span>)</span>
<span id="cb4-50"><a href="#cb4-50"></a>}</span>
<span id="cb4-51"><a href="#cb4-51"></a></span>
<span id="cb4-52"><a href="#cb4-52"></a>data_forecast &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">create_lagged_df</span>(data_seatbelts, <span class="dt">type =</span> <span class="st">&quot;forecast&quot;</span>, <span class="dt">method =</span> <span class="st">&quot;direct&quot;</span>,</span>
<span id="cb4-53"><a href="#cb4-53"></a>                                              <span class="dt">outcome_col =</span> <span class="dv">1</span>, <span class="dt">lookback =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">15</span>, <span class="dt">horizon =</span> horizons)</span>
<span id="cb4-54"><a href="#cb4-54"></a></span>
<span id="cb4-55"><a href="#cb4-55"></a>data_forecasts_ridge &lt;-<span class="st"> </span><span class="kw">predict</span>(model_results, <span class="dt">prediction_function =</span> <span class="kw">list</span>(prediction_fun), <span class="dt">data =</span> data_forecast)</span>
<span id="cb4-56"><a href="#cb4-56"></a><span class="co">#------------------------------------------------------------------------------</span></span>
<span id="cb4-57"><a href="#cb4-57"></a><span class="co"># Forecast combination.</span></span>
<span id="cb4-58"><a href="#cb4-58"></a></span>
<span id="cb4-59"><a href="#cb4-59"></a>data_forecasts &lt;-<span class="st"> </span>forecastML<span class="op">::</span><span class="kw">combine_forecasts</span>(data_forecasts_lasso, data_forecasts_ridge,</span>
<span id="cb4-60"><a href="#cb4-60"></a>                                                <span class="dt">type =</span> <span class="st">&quot;horizon&quot;</span>, <span class="dt">aggregate =</span> stats<span class="op">::</span>median)</span>
<span id="cb4-61"><a href="#cb4-61"></a></span>
<span id="cb4-62"><a href="#cb4-62"></a><span class="kw">plot</span>(data_forecasts, <span class="dt">data_actual =</span> data_seatbelts[<span class="op">-</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">170</span>), ], <span class="dt">actual_indices =</span> (<span class="dv">1</span><span class="op">:</span><span class="kw">nrow</span>(data_seatbelts))[<span class="op">-</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">170</span>)])</span></code></pre></div>
<p><img src="" /><!-- --></p>
<hr />
</div>
</div>



<!-- code folding -->


<!-- dynamically load mathjax for compatibility with self-contained -->
<script>
  (function () {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src  = "https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML";
    document.getElementsByTagName("head")[0].appendChild(script);
  })();
</script>

</body>
</html>
